#region license
/*
 * Copyright (C) 2007 CchenSoft.com
 * 
 * This library is free software; you can redistribute it and/or modify it 
 * under the terms of the GNU Lesser General Public License 2.1 or later, as
 * published by the Free Software Foundation. See the included License.txt
 * or http://www.gnu.org/copyleft/lesser.html for details.
 * 
 * Author: Billy Zhang
 */
#endregion

using System;
using System.Globalization;
using System.IO;
using System.Web;
using System.Xml;
using CchenSoft.Portal.Blog.Model;
using CchenSoft.Portal.Util;
using CchenSoft.Portal.Blog.Service;

namespace CchenSoft.Portal.Blog.Tracking
{
	/// <summary>
	/// Service used to receive trackbacks from remote clients.
	/// </summary>
	public class TrackBackHandler : IHttpHandler
	{
        private IBlogService blogService;

		/// <summary>
		/// Enables processing of HTTP Web requests by a custom
		/// <see langword="HttpHandler "/>
		/// that implements the <see cref="T:System.Web.IHttpHandler"/> interface.
		/// </summary>
		/// <param name="context">An <see cref="T:System.Web.HttpContext"/> object that provides references to the intrinsic server objects (for example, <see langword="Request"/>, <see langword="Response"/>, <see langword="Session"/>, and <see langword="Server"/>)<see langword=""/> used to service HTTP requests.</param>
		public void ProcessRequest(HttpContext context)
		{
			try
			{
                PortletContext portletContext = (PortletContext)context.Items["portlet_context"];
                blogService = portletContext.GetService<IBlogService>();

				HandleTrackback(context);
			}
			catch
			{
			}
		}

		private void HandleTrackback(HttpContext context)
		{
			context.Response.ContentType = "text/xml";

            int postId = ConvertUtil.ToInt32(Path.GetFileNameWithoutExtension(context.Request.Path));
            Post post = null;

            if (postId > 0)
                post = blogService.LoadPost(postId);

            if (post == null)
            {
                //Log.Info(string.Format("Could not extract entry id from incoming URL '{0}' .", context.Request.Path));
                SendTrackbackResponse(context, 1, "PostID is invalid or missing");
                return;
            }

            if (context.Request.HttpMethod == "POST")
            {
                CreateTrackbackAndSendResponse(context, post);
            }
            else
            {
                SendTrackbackRss(context, post);
            }
		}

		private static void SendTrackbackRss(HttpContext context, Post post)
		{	    
		    XmlTextWriter w = new XmlTextWriter(context.Response.Output) ;
			w.Formatting = Formatting.Indented;

			w.WriteStartDocument() ;
			w.WriteStartElement("response") ;
			w.WriteElementString("error", "0") ;
			w.WriteStartElement("rss") ;
			w.WriteAttributeString("version", "0.91") ;
			w.WriteStartElement("channel") ;
			w.WriteElementString("title", post.Title ) ;
			w.WriteElementString("link", string.Format("/blog/trackback/{0}.aspx", post.PostID));
			w.WriteElementString("description", "" ) ;
			w.WriteElementString("language", "en-us" ) ;

			w.WriteEndElement(); // channel
			w.WriteEndElement(); // rss 
			w.WriteEndElement(); // response
			w.WriteEndDocument();
		}

		private void CreateTrackbackAndSendResponse(HttpContext context, Post post)
		{
            PostComment comment = new PostComment();
            comment.Type = CommentType.PingTrack;

            comment.Title = ParamUtil.GetString(context.Request, "title");
            comment.Content = ParamUtil.GetString(context.Request, "excerpt");
            comment.SourceUrl = ParamUtil.GetString(context.Request, "url");
            comment.UserName = ParamUtil.GetString(context.Request, "blog_name");

            Uri url = new Uri(comment.SourceUrl);
            if(url == null)
            {
                SendTrackbackResponse(context, 1, "no url parameter found, please try harder!");
                return;
            }

            if (post == null)
            {
                SendTrackbackResponse(context, 2, "Sorry couldn't find a relevant link in " + url );
                return;
            }

            comment.PostID = post.PostID;

            PortletContext portletContext = (PortletContext)context.Items["portlet_context"];
            blogService.SavePostComment(comment);
		}
		
		/// <summary>
		/// Gets a value indicating whether another request can use
		/// the <see cref="T:System.Web.IHttpHandler"/>
		/// instance.
		/// </summary>
		/// <value></value>
		public bool IsReusable
		{
			get { return true; }
		}

		private static void SendTrackbackResponse(HttpContext context, int errorNumber, string errorMessage)
		{
			XmlDocument d = new XmlDocument();
			XmlElement root = d.CreateElement("response");
			d.AppendChild(root) ;
			XmlElement er = d.CreateElement("error");
			root.AppendChild(er) ;
			er.AppendChild(d.CreateTextNode(errorNumber.ToString(CultureInfo.InvariantCulture)));
			if (errorMessage.Length > 0)
			{
				XmlElement msg = d.CreateElement("message");
				root.AppendChild(msg) ;
				msg.AppendChild(d.CreateTextNode(errorMessage));
			}
			d.Save(context.Response.Output);
			context.Response.Output.Flush();
		}

		private static string SafeParam(HttpContext context, string pName)
		{
			if (context.Request.Form[pName] != null)
				return context.Request.Form[pName];
			return string.Empty;
		}
	}
}